package oa.service.impl;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.jbpm.api.ProcessEngine;
import org.jbpm.api.ProcessInstance;
import org.jbpm.api.history.HistoryProcessInstance;
import org.jbpm.api.history.HistoryTask;
import org.jbpm.api.task.Task;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import oa.dao.ApproveDao;
import oa.dao.FormDao;
import oa.dao.FormTemplateDao;
import oa.domain.system.User;
import oa.domain.workflow.Approve;
import oa.domain.workflow.FormTemplate;
import oa.domain.workflow.TaskView;
import oa.domain.workflow.Form;
import oa.service.WorkFlowService;
import oa.util.OAUtils;
import oa.util.UploadUtils;

@Service("workFlowService")
public class WorkFlowServiceImpl implements WorkFlowService {

	@Resource(name = "formTemplateDao")
	private FormTemplateDao formTemplateDao;

	@Resource(name="formDao")
	private FormDao formDao;
	
	@Resource(name="approveDao")
	private ApproveDao approveDao;

	@Resource(name = "processEngine")
	private ProcessEngine processEngine;

	@Override
	/**
	 * 提交申请
	 */
	@Transactional(readOnly=false)
	public void submit(File resource, Long ftid, String processKey) {
		// TODO Auto-generated method stub
		 
		//1.上传form表单
        //2.保存form表的数据
        //3.启动流程实例
        //4.完成任务
	    // 完成文件的上传
		String url = UploadUtils.saveUploadFile(resource,"/WEB-INF/upload");
		//form对象填充值
		Form form = new Form();
		Date time = new Date();
		User user = OAUtils.getUserFromSession();
	
		form.setApplicator(user.getUsername());
		form.setApplicatetime(time);

		FormTemplate formTemplate = formTemplateDao.getEntryById(ftid);
		form.setFormTemplate(formTemplate);
		form.setState("申请中...");
		form.setUrl(url);

		form.setTitle(formTemplate.getName() +"_"+ user.getUsername()+"_"+time);
		this.formDao.saveEntity(form);

		//启动流程实例
		 //放在流程实例中的form数据必须是hibernate的持久化对象，否则会报错的
		 //存在hibernate的一级缓存中的对象就是持久化的对象
		Map<String, Form> variables = new HashMap<String, Form>();
		variables.put("form", form);
		ProcessInstance processInstance = this.processEngine.getExecutionService().startProcessInstanceByKey(
				processKey, variables);
		
		//把piid赋值给form
		form.setPiid(processInstance.getId());
		  //完成任务
		 //根据piid获取该流程实例当前正在执行的任务
		Task task = this.processEngine.getTaskService().createTaskQuery()
				.executionId(processInstance.getId()).uniqueResult();
		this.processEngine.getTaskService().completeTask(task.getId());
	}

	@Override
	/**
	 * 查询我的正在完成的任务
     * 方案一
     * 如果使用该方案，在页面显示数据的时候：
	 *   <s:property value="title"/>
	 */
	public Collection<Form> myTaskList() {
		// TODO Auto-generated method stub

		/**
		 * 根据当前的登录人查询出正在执行的任务
		 */
		String username = OAUtils.getUserFromSession().getUsername();
		List<Task> taskList = this.processEngine.getTaskService().createTaskQuery()
				.assignee(username).list();
		Collection<Form> list = new ArrayList<Form>();
		for (Task task : taskList) {
			Form form = (Form)this.processEngine.getExecutionService().getVariable(task.getExecutionId(), "form");
			list.add(form);
		}
		return list;
	}

	@Override
	/**
	 * 查询我的正在完成的任务
     * 方案二
     * 如果使用该方案，在页面显示数据的时候：
	 *   <s:property value="form.title"/>
	 *   <s:prototype value="task.id"/>
	 */
	public Collection<TaskView> myTaskList2() {
		// TODO Auto-generated method stub
		String username = OAUtils.getUserFromSession().getUsername();
		List<Task> taskList = this.processEngine.getTaskService().createTaskQuery().assignee(username).list();
		List<TaskView> taskViews = new ArrayList<TaskView>();
		for (Task task : taskList) {
			Form form = (Form) this.processEngine.getExecutionService()
					.getVariable(task.getExecutionId(), "form");
			TaskView taskView = new TaskView();
			taskView.setForm(form);
			taskView.setTask(task);
			taskViews.add(taskView);
		}
		return taskViews;
	}

	@Override
	@Transactional(readOnly=false)
	public void approve(Long fid,Long taskId,String isapprove ,String comment) {
		// TODO Auto-generated method stub
		/**
		 * 如果在页面上点击的是不同意，则流程实例直接结束
		 *    改变相应的form表中state字段的值为"未通过"
		 * 如果页面上点击的是同意
		 * 	  1、完成任务
		 * 	  2、判断当前的流程实例是否已经结束
		 *        如果没有结束，则什么都不做
		 *        如果结束，改变form表中相应的state字段的值"已通过"
		 * 
		 * 在approve表中插入一行数据
		 */
		
		
		/**
		 * 如果值传递一个fid
		 *    1、根据fid把form对象提取出来
		 *    2、根据form对象获取到piid
		 *    3、根据piid把当前流程实例正在执行的任务提取出来
		 *    4、根据任务可以得到taskId
		 *    5、完成任务
		 * 如果值传递两个参数:fid,taskid
		 *    这样可以根据taskId直接完成任务
		 */
		
		/**
		 * 页面上传递过来一个字符串：是否同意
		 */
		 Form form = formDao.getEntryById(fid);	
		 System.out.println(form.getPiid());
		if(isapprove.equals("agree")){
			//完成任务
			this.processEngine.getTaskService().completeTask(taskId.toString());
			//判断流程实例是否结束	
			/*boolean bool = this.processEngine.getExecutionService().createProcessInstanceQuery()
			.processInstanceId(form.getPiid()).uniqueResult().isEnded();
			if(bool)*/
			List<HistoryProcessInstance> hpiList =  this.processEngine.getHistoryService()
			.createHistoryProcessInstanceQuery()
		     .processInstanceId(form.getPiid())
		     .state("ended")
		     .list();
			if(hpiList.size() != 0)
			{
				//如果结束，则改变form表中相应的行的state状态的值
			  form.setState("通过");
			}
		}else{
			//直接结束流程实例
			this.processEngine.getExecutionService()
			.endProcessInstance(form.getPiid(), "failed");
			//改变form表的状态
			form.setState("未通过");
			
		}
		//往approve表中插入一行数据
		String username = OAUtils.getUserFromSession().getUsername();
		Approve approve = new Approve();
		approve.setApprovename(username);
		approve.setApprovetime(new Date());
		approve.setComment(comment);
		approve.setForm(form);
		if("agree".equals(isapprove))
		{			
			approve.setIsapprove(true);
		}
		else
		{
			approve.setIsapprove(false);
		}
		this.approveDao.saveEntity(approve);
	}


}